/*!
 Temelia - Performance test case interface for Temelia
 data structures library.

 Copyright (C) 2009 Ceata (http://cod.ceata.org/proiecte/temelia).

 @author Dascalu Laurentiu

 This program is free software; you can redistribute it and
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 3
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#ifndef TESTCASE_HPP_
#define TESTCASE_HPP_

#ifndef TEMELIA
#define TEMELIA_S    ("temelia")
#endif

#ifndef STL
#define STL_S        ("STL")
#endif

#define DEBUG

#include <map>
#include <string>
#include <list>
#include <fstream>
#include "performance.hpp"

class TestCase
{
public:
	std::map<int, double> *results;
	std::string *libraryName;
	std::string *functionName;
	std::string *key;
	std::string *value;

public:
	explicit TestCase(const char *libraryName, const char *functionName);
	~TestCase();
	void addTest(int size, double time);
	void setComment(const char *key, const char *value);
};

class TestUnit
{
private:
	std::string *testName;
	std::list<TestCase *> *tests;

public:
	TestUnit(const char *testName);
	~TestUnit();
	void addTestUnit(TestCase *testUnit);
	void write(std::ofstream *fout);

#ifdef DEBUG
	void debug();
#endif
};

#define MAX_TEST_SIZE     (1000000)

// Variables used by all performance tests
extern clock_t start, stop;
extern int *default_collection[];

#ifdef CLUSTER_RUNNING
#define EXTERN_CONST extern const
#else
#define EXTERN_CONST extern
#endif

EXTERN_CONST int test_size[];
EXTERN_CONST int ntests;

double execute(void(*function)(int), int size);

/*
 * Generic test case generation using user default test sizes.
 */
#define GENERATE_TEMELIA_TEST2(testUnit, functionName, functionID, ntests, test_size)\
do\
{\
	TestCase *t_temelia_##functionID = new TestCase(TEMELIA_S, functionName);\
	for (int i = 0; i < ntests; i++)\
		t_temelia_##functionID->addTest(test_size[i], execute(temelia_##functionID, test_size[i]));\
	testUnit.addTestUnit(t_temelia_##functionID);\
} while(0)

#define GENERATE_STL_TEST2(testUnit, functionName, functionID, ntests, test_size)\
do\
{\
	TestCase *t_stl_##functionID = new TestCase(STL_S, functionName);\
	for (int i = 0; i < ntests; i++)\
		t_stl_##functionID->addTest(test_size[i], execute(stl_##functionID, test_size[i]));\
	testUnit.addTestUnit(t_stl_##functionID);\
} while(0)

/*!
 * Test cases generation using default test sizes.
 */
#define GENERATE_TEMELIA_TEST(testUnit, functionName, functionID)\
do\
{\
	GENERATE_TEMELIA_TEST2(testUnit, functionName, functionID, ntests, test_size);\
} while(0)

#define GENERATE_STL_TEST(testUnit, functionName, functionID)\
do\
{\
	GENERATE_STL_TEST2(testUnit, functionName, functionID, ntests, test_size);\
}while(0)

#endif /* TESTCASE_HPP_ */
